{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UncprnB0ymAE"
   },
   "source": [
    "Below is code with a link to a happy or sad dataset which contains 80 images, 40 happy and 40 sad. \n",
    "Create a convolutional neural network that trains to 100% accuracy on these images,  which cancels training upon hitting training accuracy of >.999\n",
    "\n",
    "Hint -- it will work best with 3 convolutional layers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 210
    },
    "colab_type": "code",
    "id": "7Vti6p3PxmpS",
    "outputId": "5120cb68-d553-4dce-b25b-7b2b56fbb54c"
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import os\n",
    "import zipfile\n",
    "\n",
    "\n",
    "DESIRED_ACCURACY = 0.999\n",
    "\n",
    "!wget --no-check-certificate \\\n",
    "    \"https://storage.googleapis.com/laurencemoroney-blog.appspot.com/happy-or-sad.zip\" \\\n",
    "    -O \"happy-or-sad.zip\"\n",
    "\n",
    "zip_ref = zipfile.ZipFile(\"happy-or-sad.zip\", 'r')\n",
    "zip_ref.extractall(\"h-or-s\")\n",
    "zip_ref.close()\n",
    "\n",
    "class myCallback(tf.keras.callbacks.Callback):\n",
    "  # Your Code\n",
    "  def on_epoch_end(self, epoch, logs={}):\n",
    "    if (logs.get('acc') > 0.999):\n",
    "      print(\"\\nReached 99.9% accuracy so cancelling training!\")\n",
    "      self.model.stop_training = True\n",
    "\n",
    "callback = myCallback()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 90
    },
    "colab_type": "code",
    "id": "6DLGbXXI1j_V",
    "outputId": "be72bf85-ac7f-4a89-ed51-62e680405abc"
   },
   "outputs": [],
   "source": [
    "# This Code Block should Define and Compile the Model\n",
    "model = tf.keras.models.Sequential([\n",
    "  # Your Code Here\n",
    "  tf.keras.layers.Conv2D(32, (3,3), activation=\"relu\", input_shape=(150, 150, 3)),\n",
    "  tf.keras.layers.MaxPooling2D(2, 2),\n",
    "  tf.keras.layers.Conv2D(64, (3,3), activation=\"relu\"),\n",
    "  tf.keras.layers.MaxPooling2D(2, 2),\n",
    "  tf.keras.layers.Conv2D(64, (3,3), activation=\"relu\"),\n",
    "  tf.keras.layers.MaxPooling2D(2, 2),\n",
    "  tf.keras.layers.Conv2D(64, (3,3), activation=\"relu\"),\n",
    "  tf.keras.layers.MaxPooling2D(2, 2),\n",
    "  tf.keras.layers.Flatten(),\n",
    "  tf.keras.layers.Dense(1024, activation=\"relu\"),\n",
    "  tf.keras.layers.Dense(1, activation=\"sigmoid\")\n",
    "])\n",
    "\n",
    "from tensorflow.keras.optimizers import RMSprop\n",
    "\n",
    "model.compile(loss=\"binary_crossentropy\", optimizer=RMSprop(lr=0.001), metrics=['acc'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 34
    },
    "colab_type": "code",
    "id": "4Ap9fUJE1vVu",
    "outputId": "9720fbf7-d145-4e2f-d65a-d75a3eec794b"
   },
   "outputs": [],
   "source": [
    "# This code block should create an instance of an ImageDataGenerator called train_datagen \n",
    "# And a train_generator by calling train_datagen.flow_from_directory\n",
    "\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "train_datagen = ImageDataGenerator(rescale=1/255.0) # Your Code Here\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "    'h-or-s/',\n",
    "    target_size=(150, 150),\n",
    "    batch_size=32,\n",
    "    class_mode='binary')\n",
    "\n",
    "# Expected output: 'Found 80 images belonging to 2 classes'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 688
    },
    "colab_type": "code",
    "id": "48dLm13U1-Le",
    "outputId": "341c817b-b32f-469d-f986-64b8997889d8"
   },
   "outputs": [],
   "source": [
    "# This code block should call model.fit_generator and train for\n",
    "# a number of epochs. \n",
    "history = model.fit_generator(train_generator, steps_per_epoch=2, epochs=30, verbose=1, callbacks=[callback])\n",
    "    \n",
    "# Expected output: \"Reached 99.9% accuracy so cancelling training!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "INRbfQJTlcnK"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "name": "Exercise4-Question.ipynb",
   "provenance": [],
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python (Python 3.6)",
   "language": "python",
   "name": "python36"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
